﻿using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace E.Tool
{
    [Serializable]
    public class FloatProperty
    {
        [Tooltip("目标值")] [SerializeField] private float target;
        [Tooltip("当前值")] [SerializeField] private float now;
        [Tooltip("最小值")] [SerializeField] private float min;
        [Tooltip("最大值")] [SerializeField] private float max;
        [Tooltip("自动增加")] [SerializeField] private float autoAdd;
        [Tooltip("更新插值")] [SerializeField] private float step;

        public float Target { get => target; }
        public float Now { get => now; }
        public float Max { get => max; }
        public float Min { get => min; }
        public float AutoAdd { get => autoAdd; set => autoAdd = value; }
        public float NowPercent
        {
            get
            {
                if (max == 0) return 0;
                else return now / max;
            }
        }
        public float TargetPercent
        {
            get
            {
                if (max == 0) return 0;
                else return target / max;
            }
        }
        public bool IsNowTarget { get => Mathf.Abs(target - now) < 0.001f; }
        public bool IsNowMax { get => now >= max; }
        public bool IsNowMin { get => now <= min; }

        public FloatProperty(float now, float min, float max,  float autoAdd = 0)
        {
            if (max < min)
            {
                Debug.LogError("最大值不能小于最小值，已自动交换两个数值");
                float temp = max;
                max = min;
                min = temp;
            }
            if (now < min || now > max)
            {
                Debug.LogError("当前值不能超出最大值与最小值的限定范围，已自动设置为最大值");
                now = max;
            }

            target = now;
            this.now = now;
            this.min = min;
            this.max = max;
            this.autoAdd = autoAdd;
        }

        public void SetTargetPercent(float value)
        {
            target = Utility.Clamp(max * value, min, max);
            CheckStep();
        }
        public void SetTarget(float value)
        {
            target = Utility.Clamp(value, min, max);
            CheckStep();
        }
        public void SetNow(float value)
        {
            now = Utility.Clamp(value, min, max);
        }
        public void SetMin(float value)
        {
            min = Utility.ClampMax(value, max);
        }
        public void SetMax(float value)
        {
            max = Utility.ClampMin(value, min);
        }

        public bool AddTarget(float value)
        {
            bool result = Utility.TryClamp(target + value, min, max, out float newValue);
            target = newValue;
            CheckStep();
            return result;
            //now = Utility.Clamp(now + value, min, max);
        }
        public bool AddNow(float value)
        {
            bool result = Utility.TryClamp(now + value, min, max, out float newValue);
            now = newValue;
            return result;
            //now = Utility.Clamp(now + value, min, max);
        }
        public void AddMin(float value)
        {
            min = Utility.ClampMax(min + value, max);
        }
        public void AddMax(float value)
        {
            max = Utility.ClampMin(max + value, min);
        }
        public bool AddNowPercent(float value)
        {
            bool result = Utility.TryClamp(now + max * value, min, max, out float newValue);
            now = newValue;
            return result;
            //now = Utility.Clamp(now + max * value, min, max);
        }

        public void Update()
        {
            //AddTarget(AutoAdd);

            if (step == 0) return;
            float f = target - now;
            if (Mathf.Abs(f) <= step)
            {
                now = target;
                step = 0;
            }
            else
            {
                if (f > 0)
                {
                    AddNow(step);
                }
                else
                {
                    AddNow(-step);
                }
            }
        }
        private void CheckStep()
        {
            float f = Mathf.Abs(target - now) * 0.05f;
            if (f < 0.2f)
            {
                f = 0.2f;
            }
            step = f;
        }
    }
}